<template>
  <a-card class="container fillNoHeaderFlex">
    <div class="toolbar" v-if="!toolbarHidden">
      <slot name="tollbarPre" />
      <a-button icon="reload" @click="onRefresh">刷新</a-button>
      <a-divider type="vertical" />
      <a-button type="primary" icon="plus" @click="onAddBtnClick">新增</a-button>
      <a-button type="danger" icon="fa fa-trash-o" @click="onDeleteBtnClick">删除</a-button>
      <slot name="toolbarEx" />
      <slot name="toolbarTips" />
    </div>

    <a-table ref="table" :columns="columns" :pagination="pagination" :rowKey="record => record.id" :dataSource="tbData" :loading="tbLoading"
      :scroll="{x: false, y : tbBodyHeight}" :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}" class="table scroll"
      size="small" bordered @change="onTableChange">
      <template slot="action" slot-scope="text, record">
        <a-button size="small" icon="fa fa-edit" class="actionBtn" @click="onEditActionClick(record)" />
        <a-button size="small" icon="fa fa-trash-o" class="actionBtn" @click="onDeleteActionClick(record.id)" type="danger" />
      </template>
      <span slot="disable" slot-scope="text">
        <a-tag color="red" v-if="text">是</a-tag>
        <a-tag color="blue" v-if="!text">否</a-tag>
      </span>
      <template v-for="col in columns" :slot="`slotEX_${col.dataIndex}`" slot-scope="text, record">
        <slot :name="`slotEX_impl_${col.dataIndex}`" :text="text" :record="record" />
      </template>
    </a-table>

    <a-drawer :title="titleText" :width="drawerWidth" destroyOnClose :visible="drawerVisible" :maskClosable="false" :wrapStyle="wrapStyle"
      :bodyStyle="bodyStyle" @close="onDrawerClose">
      <div class="drawerBody">
        <a-form :form="form" layout="vertical">
          <slot name="formItems" :record="formData" />
        </a-form>
      </div>
      <div class="drawerFooter">
        <a-button type="primary" icon="fa fa-check" @click="onSubmit" class="button">{{submitBtnText}}</a-button>
        <a-button icon="fa fa-remove" @click="onCancel" class="button">取消</a-button>
      </div>
    </a-drawer>

  </a-card>
</template>

<script>
// import moment from 'moment';
import axios from '@/libs/api.request';

/**
 * 在编辑模式时，form-item class 为 add-hidden 的隐藏
 */
export default {
  name: 'crud',
  props: {
    tbColumns: {
      type: Array,
      default: () => {
        return [];
      }
    },
    title: String,
    // 刷新、查询用 url，其缺省值为 baseUrl
    refreshUrl: String,
    // 基准url，增删改用，
    baseUrl: {
      type: String,
      required: true
    },
    toolbarHidden: {
      type: Boolean,
      default: false
    }
  },

  inject: ['beforeDrawerShow'],

  data() {
    return {
      // table 属性相关
      columns: [],
      tbData: [],
      curBaseUrl: String,
      tbLoading: false,
      tbBodyHeight: 720,
      selectedRowKeys: [],
      selectedRows: [],
      pagination: {
        defaultCurrent: 1,
        defaultPageSize: 20,
        current: 1,
        showSizeChanger: true,
        showQuickJumper: true,
        showTotal: (total, range) => `总计 ${total} 条`
      },
      queryParams: {},
      // 批量删除个数，当删除完时，刷新表格
      batchDeleteLength: 0,

      // drawer 属性相关
      drawerVisible: false,
      drawerWidth: window.innerWidth / 2.8,
      wrapStyle: { overflow: 'auto' },
      bodyStyle: {
        height: 'calc(100% - 56px)',
        display: 'flex',
        'flex-direction': 'column',
        '-webkit-flex-direction': 'column',
        padding: '0'
      },

      // form 相关
      isEdit: null,
      formData: { id: 100 }
    };
  },

  watch: {
    tbColumns: {
      handler(newVal) {
        let initColumns = [{ title: '操作', fixed: 'left', width: 85, scopedSlots: { customRender: 'action' } }];
        this.columns = initColumns.concat(newVal);
      },
      immediate: true
    },
    isEdit: {
      handler(newVal, oldVal) {
        this.$emit('editChange', newVal);
      },
      immediate: true
    }
  },

  computed: {
    submitBtnText() {
      return this.isEdit ? '修改' : '添加';
    },
    titleText() {
      return this.title + '\t-\t' + (this.isEdit ? '修改' : '添加');
    },
    selectTreeNode() {
      return this.$store.state.treeSelect;
    }
  },

  beforeCreate() {
    this.form = this.$form.createForm(this);
  },

  created() {
    var _this = this;
    document.onkeydown = function(e) {
      if (window.event.keyCode === 27) {
        _this.closeDrawer();
      }
    };
  },

  mounted() {
    this.resizeTbBodyHeight();
    this.$bus.on(this.$constant.BUS_EVENT.RESIZE, item => {
      this.resizeTbBodyHeight();
    });
  },

  methods: {
    onRefresh() {
      let url = this.getRefreshUrl();
      this.loadTableData(url, this.getRequestParams());
    },

    onTableChange(pagination, filters, sorter) {
      let url = this.getRefreshUrl();
      this.pagination.current = pagination.current;
      this.loadTableData(url, Object.assign(this.getRequestParams(), { page: pagination.current, size: pagination.pageSize }));
    },

    refreshCurPage() {
      let url = this.getRefreshUrl();
      this.loadTableData(url, Object.assign(this.getRequestParams(), { page: this.pagination.current, size: this.pagination.pageSize }));
    },

    onSelectChange(selectedRowKeys, selectedRows) {
      this.selectedRowKeys = selectedRowKeys;
      this.selectedRows = selectedRows;
    },

    loadTableData(url, params) {
      if (url.includes('{')) {
        throw Error(`url解析失败，无法请求后台，路径为:${url}`);
      }
      this.tbLoading = true;
      axios
        .request({ url: url, method: 'GET', params: params })
        .then(res => {
          this.tbData = res.data.content;
          const pagination = { ...this.pagination };
          pagination.total = res.data.totalElements;
          pagination.pageSize = res.data.size;
          this.pagination = pagination;
        })
        .catch()
        .finally(res => {
          this.tbLoading = false;
        });
    },

    getRefreshUrl() {
      // 目前占位符只处理一层
      let result = this.refreshUrl ? this.refreshUrl : this.baseUrl;
      if (result.includes('{')) {
        let reg = /\{[a-zA-Z0-9_]+\}/g;
        let keywords = result.match(reg);
        keywords.forEach(item => {
          let keywordStr = item.replace('{', '').replace('}', '');
          if (this.selectTreeNode[keywordStr]) {
            result = result.replace(item, this.selectTreeNode[keywordStr]);
          }
        });
      }
      return result;
    },

    getRequestParams() {
      let requestParams = {
        page: this.pagination.defaultCurrent,
        size: this.pagination.defaultPageSize
      };
      // UNDO
      // if (this.searchValue !== '') {
      //   requestParams.q = this.searchValue;
      // }
      Object.assign(requestParams, this.queryParams);
      return requestParams;
    },

    onAddBtnClick() {
      this.showDraswer();
      this.isEdit = false;
      this.formData = {};
      // 父组件 provide 一个 beforeDrawerShow 方法即可
      this.beforeDrawerShow && this.beforeDrawerShow(this.formData);
    },

    onDeleteBtnClick() {
      this.batchDeleteLength = this.selectedRowKeys.length;
      if (this.batchDeleteLength < 1) {
        this.$message.warning('未选择可删除项，无法执行删除功能；');
        return;
      }
      var me = this;
      this.$confirm({
        title: '删除确认',
        content: `是否确认删除选中的${this.batchDeleteLength}项?`,
        onOk() {
          me.selectedRowKeys.forEach(id => {
            me.doDelete(id, true);
          });
        }
      });
    },

    onEditActionClick(record) {
      this.formData = JSON.parse(JSON.stringify(record));
      this.isEdit = true;
      this.showDraswer();
    },

    onDeleteActionClick(id) {
      var me = this;
      this.$confirm({
        title: '删除确认',
        content: '是否确认删除选中项?',
        onOk() {
          me.doDelete(id, false);
        }
      });
    },

    onDrawerClose() {
      this.closeDrawer();
    },

    onSubmit() {
      console.log(this.formData);
      this.form.validateFields((err, values) => {
        if (!err) {
          axios
            .request({
              url: this.baseUrl,
              method: 'PUT',
              data: this.formData
            })
            .then(res => {
              this.afterOk && this.afterOk(res.data.data);
              this.closeDrawer();
              this.$message.success('操作成功');
              this.refreshCurPage();
            });
        }
      });
    },
    onCancel() {
      this.closeDrawer();
    },

    showDraswer() {
      this.drawerVisible = true;
    },
    closeDrawer() {
      this.drawerVisible = false;
    },
    /**
     * batch：批量删除时，不更新表格，否则影响效率
     */
    doDelete(id, batch) {
      axios
        .request({
          url: `${this.baseUrl}/${id}`,
          method: 'delete'
        })
        .then(res => {
          this.$message.success('删除成功');
          batch || this.refreshCurPage();
        })
        .finally(() => {
          this.batchDeleteLength = this.batchDeleteLength - 1;
        });
    },

    resizeTbBodyHeight() {
      this.$nextTick(() => {
        this.$nextTick(() => {
          var table = this.$refs.table;
          console.log(table.$parent.$el.clientHeight);
          this.tbBodyHeight = table.$parent.$el.clientHeight - 32 - 46 - 25 - 50;
        });
      });
    }
  }
};
</script>

<style lang="less" scoped>
.container {
  height: 100%;
}

.toolbar {
  // none
}
.table {
  flex: 1;
}

.drawerBody {
  flex: 1;
  overflow: auto;
  padding: 16px;
}
.drawerFooter {
  border-top: 1px solid #e9e9e9;
  text-align: center;
  padding: 8px 16px;
  background-color: rgba(0, 0, 0, 0.02);

  .button {
    width: 120px;
  }
}
</style>
